#include <QDebug>
#include "videoplayer.h"
#include "ffinclude.h"
#include "demuxthread.h"
#include "renderthread.h"
#include "decodethread.h"

QString VideoPlayer::dumpMediaInfo(const MediaInfo &media)
{
    return QString("url: %1 duration: %2 container: %3 videoForamt: %4 audioFormat: %5 "
                   "videoBitrate: %6 videoSize: %7 videoFps: %8 "
                   "audioBitrate: %9 audioSamplerate: %10 audioChannels: %11")
            .arg(media.url)
            .arg(media.duration>0?QString::number(media.duration/(double)1000,'f',3)+"s":"N/A")
            .arg(media.containerFormat)
            .arg(media.videoFormat)
            .arg(media.audioFormat)
            .arg(media.videoBitrate>0?(QString::number(media.videoBitrate)+"kb/s"):"N/A")
            .arg(media.videoFrameWidth>0?(QString::number(media.videoFrameWidth)+"x"+QString::number(media.videoFrameHeight)):"N/A")
            .arg(media.videoFramerate)
            .arg(media.audioBitrate>0?(QString::number(media.audioBitrate)+"kb/s"):"N/A")
            .arg(media.audioSamplerate>0?(QString::number(media.audioSamplerate)+"hz"):"N/A")
            .arg(media.audioChannels>0?QString::number(media.audioChannels):"N/A");

}

VideoPlayer::VideoPlayer(QObject *parent) : QObject(parent)
{
    m_playerInfo.videoFrameQueue.inited=false;
    m_playerInfo.audioFrameQueue.inited=false;
    m_playerInfo.textFrameQueue.inited=false;
    m_playerInfo.videoPacketQueue.inited=false;
    m_playerInfo.audioPacketQueue.inited=false;
    m_playerInfo.textPacketQueue.inited=false;

    m_playerConfig.speed=1.0;
    m_playerConfig.startPos=0;
    m_playerConfig.timeout=5000;
    m_playerConfig.rtspWithTcp=5000;
    m_playerConfig.videoEnable=true;
    m_playerConfig.audioEnable=true;
    m_playerConfig.textEnable=true;
    m_playerConfig.loop=5000;
    m_playerConfig.maxProbeSize=1024*3;

    m_playerConfig.acodecName="";
    m_playerConfig.vcodecName="";
    m_playerConfig.codecThreads=-1;
    m_playerConfig.fastMode=false;
    m_playerConfig.lowers=0;
    m_playerConfig.reorderPts=false;
    m_playerConfig.framedrop=false;

    m_playerConfig.avType=AV_SYNC_AUDIO_MASTER;
    m_playerConfig.winId=NULL;
    m_playerConfig.renderRect=QRect();
    m_playerConfig.hwRender=false;
    m_playerConfig.volume=100;
    m_playerConfig.muted=false;
    m_playerConfig.fill=false;
    m_playerConfig.keepLastFrame=true;

    m_state=Stoped;

    m_demuxThread=new DemuxThread(this);
    m_vcodecThread=new DecodeThread(DecodeThread::VideoDecode,this);
    m_acodecThread=new DecodeThread(DecodeThread::AudioDecode,this);
    m_textcodecThread=new DecodeThread(DecodeThread::TextDecode,this);
    m_renderThread=new RenderThread(this);

    connect(m_demuxThread,&DemuxThread::inited,this,&VideoPlayer::onThreadInited);
    connect(m_demuxThread,&DemuxThread::error,this,&VideoPlayer::onThreadError);
    connect(m_demuxThread,&DemuxThread::finished,this,&VideoPlayer::onThreadExited);
    connect(m_demuxThread,&DemuxThread::eof,this,&VideoPlayer::onDemuxThreadEof);
    connect(m_demuxThread,&DemuxThread::seekDone,this,&VideoPlayer::onDemuxThreadSeekDone);

    connect(m_vcodecThread,&DecodeThread::inited,this,&VideoPlayer::onThreadInited);
    connect(m_vcodecThread,&DecodeThread::error,this,&VideoPlayer::onThreadError);
    connect(m_vcodecThread,&DecodeThread::finished,this,&VideoPlayer::onThreadExited);

    connect(m_acodecThread,&DecodeThread::inited,this,&VideoPlayer::onThreadInited);
    connect(m_acodecThread,&DecodeThread::error,this,&VideoPlayer::onThreadError);
    connect(m_acodecThread,&DecodeThread::finished,this,&VideoPlayer::onThreadExited);

    connect(m_textcodecThread,&DecodeThread::inited,this,&VideoPlayer::onThreadInited);
    connect(m_textcodecThread,&DecodeThread::error,this,&VideoPlayer::onThreadError);
    connect(m_textcodecThread,&DecodeThread::finished,this,&VideoPlayer::onThreadExited);

    connect(m_renderThread,&RenderThread::inited,this,&VideoPlayer::onThreadInited);
    connect(m_renderThread,&RenderThread::error,this,&VideoPlayer::onThreadError);
    connect(m_renderThread,&RenderThread::finished,this,&VideoPlayer::onThreadExited);
}

VideoPlayer::~VideoPlayer()
{
    stop();
}

bool VideoPlayer::init()
{
    av_register_all();
    avdevice_register_all();
    avfilter_register_all();
    avformat_network_init();

    SDL_Init (SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER);
    SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
    return true;
}

void VideoPlayer::deInit()
{

}

/*
    播放
*/
void VideoPlayer::play(MediaInfo media)
{
    stop();

    m_state=Playing;
    initPlayerInfo();
    m_mediaInfo = media;
    m_demuxThread->play();

    return;
}

void VideoPlayer::stop()
{
    if(m_state!=Stoped){
        m_state=Stoped;

        //FrameQueue依靠PacketQueue停止。因此必须先关闭Demux，
        //否则Decoder可能会阻塞FrameQueue调用上
        m_demuxThread->stop();
        m_vcodecThread->stop();
        m_acodecThread->stop();
        m_textcodecThread->stop();        
        m_renderThread->stop();

        destoryPlayerInfo();
    }
}

void VideoPlayer::pause()
{
    if(m_state!=Paused){
        m_state=Paused;

        m_demuxThread->pause();
        m_renderThread->pause();
        m_vcodecThread->pause();
        m_acodecThread->pause();
        m_textcodecThread->pause();
    }
}

void VideoPlayer::resume()
{

}

bool VideoPlayer::seek(qint64 pos)
{
    return true;
}

PlayerConfig *VideoPlayer::config()
{
    return &m_playerConfig;
}

MediaInfo VideoPlayer::mediaInfo()
{
    return m_mediaInfo;
}

VideoPlayer::PlayerState VideoPlayer::state()
{
    return m_state;
}

void VideoPlayer::setWId(WId id)
{
    QWidget*w=QWidget::find(id);
    if(w){
        m_playerConfig.winId= (const void*)id;
        m_playerConfig.renderRect=QRect(0,0,230,125);
    }
    m_wid=id;
}

/*
    初始化PlayerInfo
*/
void VideoPlayer::initPlayerInfo()
{
    av_init_packet(&m_playerInfo.flushPkt);
    m_playerInfo.flushPkt.data = (uint8_t *)&m_playerInfo.flushPkt;

    //队列初始化
    frame_queue_init(&m_playerInfo.videoFrameQueue, &m_playerInfo.videoPacketQueue, VIDEO_PICTURE_QUEUE_SIZE, 1);
    frame_queue_init(&m_playerInfo.textFrameQueue, &m_playerInfo.textPacketQueue, SUBPICTURE_QUEUE_SIZE, 0);
    frame_queue_init(&m_playerInfo.audioFrameQueue, &m_playerInfo.audioPacketQueue, SAMPLE_QUEUE_SIZE, 1);

    packet_queue_init(&m_playerInfo.videoPacketQueue);
    packet_queue_init(&m_playerInfo.audioPacketQueue);
    packet_queue_init(&m_playerInfo.textPacketQueue);

    //时钟初始化
    init_clock(&m_playerInfo.videoClock, &m_playerInfo.videoPacketQueue.serial);
    init_clock(&m_playerInfo.audioClock, &m_playerInfo.audioPacketQueue.serial);
    init_clock(&m_playerInfo.externalClock, &m_playerInfo.externalClock.serial);

    //其他初始化
    m_playerInfo.continue_read_thread = SDL_CreateCond();

    m_playerInfo.isLiveStream=false;
    m_playerInfo.maxFrameDuration=0;
    m_playerInfo.demuxEof=false;
    m_playerInfo.videoCodecEof=false;
    m_playerInfo.audioCodecEof=false;
    m_playerInfo.textCodecEof=false;
    m_playerInfo.videoFrameDropsOnDecode=0;
    m_playerInfo.videoFrameDropsOnRender=0;

    m_playerInfo.masterClock=NULL;
    m_playerInfo.formatContext=NULL;
    m_playerInfo.videoStream=NULL;
    m_playerInfo.audioStream=NULL;
    m_playerInfo.textStream=NULL;
    m_playerInfo.videoCodecContext=NULL;
    m_playerInfo.videoCodec=NULL;
    m_playerInfo.audioCodecContext=NULL;
    m_playerInfo.audioCodec=NULL;
    m_playerInfo.textCodecContext=NULL;
    m_playerInfo.textCodec=NULL;
}


/*
    销毁PlayerInfo
*/
void VideoPlayer::destoryPlayerInfo()
{
    packet_queue_destroy(&m_playerInfo.videoPacketQueue);
    packet_queue_destroy(&m_playerInfo.audioPacketQueue);
    packet_queue_destroy(&m_playerInfo.textPacketQueue);

    frame_queue_destory(&m_playerInfo.videoFrameQueue);
    frame_queue_destory(&m_playerInfo.audioFrameQueue);
    frame_queue_destory(&m_playerInfo.textFrameQueue);

    if(m_playerInfo.continue_read_thread){
        SDL_DestroyCond(m_playerInfo.continue_read_thread);
        m_playerInfo.continue_read_thread=NULL;
    }

    m_playerInfo.isLiveStream=false;
    m_playerInfo.maxFrameDuration=0;
    m_playerInfo.demuxEof=false;
    m_playerInfo.videoCodecEof=false;
    m_playerInfo.audioCodecEof=false;
    m_playerInfo.textCodecEof=false;
    m_playerInfo.videoFrameDropsOnDecode=0;
    m_playerInfo.videoFrameDropsOnRender=0;

    m_playerInfo.formatContext=NULL;
    m_playerInfo.videoStream=NULL;
    m_playerInfo.audioStream=NULL;
    m_playerInfo.textStream=NULL;
    m_playerInfo.videoCodecContext=NULL;
    m_playerInfo.videoCodec=NULL;
    m_playerInfo.audioCodecContext=NULL;
    m_playerInfo.audioCodec=NULL;
    m_playerInfo.textCodecContext=NULL;
    m_playerInfo.textCodec=NULL;
}

void VideoPlayer::__error(const QString &errMsg)
{

    emit this->playerError(errMsg);
}

void VideoPlayer::onThreadInited()
{
    QObject* object=sender();
    qDebug()<<__FUNCTION__<<object->metaObject()->className()<<"已启动!";

    bool inited=true;
    if(m_playerInfo.audioStream && !m_playerInfo.audioCodec){
        inited=false;
    }
    if(m_playerInfo.videoStream && !m_playerInfo.videoCodec){
        inited=false;
    }
    if(m_playerInfo.textStream && !m_playerInfo.textCodec){
        inited=false;
    }
    if(inited){
        m_renderThread->play();
    }

    if(object==m_demuxThread){

    }else if(object==m_renderThread){

    }else if(object==m_vcodecThread){

    }else if(object==m_acodecThread){

    }else if(object==m_textcodecThread){

    }
}

void VideoPlayer::onThreadError(const QString &errMsg)
{
    QObject* object=sender();
    qDebug()<<__FUNCTION__<<object->metaObject()->className()<<"出现错误: "<<errMsg;

    stop();
}

void VideoPlayer::onThreadExited()
{
    QObject* object=sender();
    qDebug()<<__FUNCTION__<<object->metaObject()->className()<<"已退出!";

}

void VideoPlayer::onDemuxThreadInited()
{
    qDebug()<<__FUNCTION__<<"Demux线程已启动！";
}

void VideoPlayer::onVideoDecodeThreadInited()
{
    qDebug()<<__FUNCTION__<<"Video Decode线程已启动！";

    if(m_playerInfo.audioStream && m_playerInfo.audioCodec){
        m_renderThread->play();
    }
}

void VideoPlayer::onAudioDecodeThreadInited()
{
    qDebug()<<__FUNCTION__<<"Audio Decode线程已启动！";

    if(m_playerInfo.videoStream && m_playerInfo.videoCodec){
        m_renderThread->play();
    }
}

void VideoPlayer::onTextDecodeThreadInited()
{
    qDebug()<<__FUNCTION__<<"Text Decode程已启动！";
}

void VideoPlayer::onRenderThreadInited()
{
    qDebug()<<__FUNCTION__<<"Render线程已启动！"<<m_renderThread->m_audioDeviceId;
}

void VideoPlayer::onDemuxThreadError(const QString &errMsg)
{
    qDebug()<<__FUNCTION__<<errMsg;
}

void VideoPlayer::onDemuxThreadEof()
{
    qDebug()<<__FUNCTION__;
}

void VideoPlayer::onDemuxThreadSeekDone(bool success, const QString &errMsg)
{
    qDebug()<<__FUNCTION__<<success<<errMsg;

    if(success){
        //如果在暂停状态下执行了seek，则渲染下一帧
        if(m_reqPause){
            m_renderThread->step();
        }
    }
}

void VideoPlayer::onDemuxThreadExited()
{
    qDebug()<<__FUNCTION__;
}

void VideoPlayer::onVideoDecodeThreadError(const QString &errMsg)
{
    qDebug()<<__FUNCTION__<<errMsg;
}

void VideoPlayer::onVideoDecodeThreadExited()
{
    qDebug()<<__FUNCTION__;
}

void VideoPlayer::onAudioDecodeThreadError(const QString &errMsg)
{
    qDebug()<<__FUNCTION__<<errMsg;
}

void VideoPlayer::onAudioDecodeThreadExited()
{
    qDebug()<<__FUNCTION__;
}

void VideoPlayer::onTextDecodeThreadError(const QString &errMsg)
{
    qDebug()<<__FUNCTION__<<errMsg;
}

void VideoPlayer::onTextDecodeThreadExited()
{
    qDebug()<<__FUNCTION__;
}

void VideoPlayer::onRenderThreadError(const QString &errMsg)
{
    qDebug()<<__FUNCTION__<<errMsg;
}

void VideoPlayer::onRenderThreadExited()
{
    qDebug()<<__FUNCTION__;
}

void MediaInfo::init()
{

}
